package cn.tedu.csmall.passport.interceptor;

import cn.tedu.csmall.passport.annotation.RepeatSubmit;
import cn.tedu.csmall.passport.exception.ServiceException;
import cn.tedu.csmall.passport.web.ServiceCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 重复请求的拦截器
 *
 * @author Chen
 * @since 2023/2/15 8:20:20
 */
@Component
public class RepeatSubmitInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod method = (HandlerMethod) handler;
            RepeatSubmit repeatSubmitByMethod = AnnotationUtils.findAnnotation(method.getMethod(), RepeatSubmit.class);
            RepeatSubmit repeatSubmitByCls = AnnotationUtils.findAnnotation(method.getMethod().getDeclaringClass(), RepeatSubmit.class);
            if (Objects.isNull(repeatSubmitByMethod) && Objects.isNull(repeatSubmitByCls)) {
                return true;
            }
            String uri = request.getRequestURI();
            Boolean ifAbsent =
                    stringRedisTemplate.opsForValue().
                            setIfAbsent(
                                    uri, "", Objects.nonNull(repeatSubmitByMethod)
                                            ? repeatSubmitByMethod.seconds() : repeatSubmitByCls.seconds(), TimeUnit.SECONDS);
            if (ifAbsent != null && !ifAbsent) {
                String message = "短时间发送多次请求，服务器端忙，请稍后重试";
                throw new ServiceException(ServiceCode.ERR_BAD_REQUEST, message);
            }
        }
        return true;
    }
}
